if hack and hack.GUI and hack.GUI.frame then
	hack.GUI.frame:Remove()
end

hack = {}

hack.copytable = function(tabl,done) //Probably does what table.Copy() does...
	local new = {
		uidcopy = "_"
		}
	done = done or {}
	table.insert(done,tostring(tabl))
	for k,v in pairs(tabl or {}) do
		if type(v) ~= "table" then
			new[k] = v
		else
			table.insert(done,tostring(v))
			new[k] = hack.copytable(v,done)
		end
	end
	new.uidcopy = nil
	return new
end

hack.scheme = {
	c1 = Color(32,64,128,100), //Inactive/unhighlighted
	c2 = Color(128,128,128,230), //Background window pane
	c3 = Color(32,64,128,200), //Active/highlighted
	c4 = Color(255,255,32,200), //Pressed
	c5 = Color(255,0,0,200), //Over-pressed
	c6 = Color(255,255,255,200), //Text edit
	f1 = Color(255,255,255), //Default/generic text
	f2 = Color(255,0,0), //Close button highlight
	f3 = Color(255,255,32), //Close button pressed
	f4 = Color(32,128,64), //Minimize button highlight
	f5 = Color(80,80,80), //Disabled
	f6 = Color(0,0,0), //Text edit text
	border = 8, //This is not adjustable, it is a constant
}

hack.schemelabel = {
	{
		key = "c1",
		label = "GUI Inactive",
	},
	{
		key = "c3",
		label = "GUI Active",
	},
	{
		key = "c4",
		label = "GUI Pressed",
	},
	{
		key = "c5",
		label = "GUI Over-Pressed",
	},
	{
		key = "c2",
		label = "Window Background",
	},
	{
		key = "c6",
		label = "Text Entry Field",
	},
	{
		key = "f2",
		label = "Close Button Highlighted",
	},
	{
		key = "f4",
		label = "Minimize Button Highlighted",
	},
	{
		key = "f3",
		label = "Close/Minimize Button Pressed",
	},
	{
		key = "f1",
		label = "Text Default",
	},
	{
		key = "f5",
		label = "Text Disabled Button",
	},
	{
		key = "f6",
		label = "Text Entry Text",
	},
}

//include("shared.lua") //See hack.LoadData()
include("cl_forms.lua")

function hack.InitWindow(self,window)
	local window = hack.copytable(window)
	local newwindow = {
		uid = self.uid,
		}
	for i,o in pairs(window) do
		if not newwindow[i] then
			newwindow[i] = o
		end
	end
	for i,o in pairs(self.windowmeta) do
		if not newwindow[i] then
			newwindow[i] = o
		end
	end
	//window.uid = hack.uid
	self.uid = self.uid + 1
	return newwindow
end

function hack.GetFocus(self,x,y)
	x = x or self.mc.x
	y = y or self.mc.y
	
	for k,window in ipairs(self.windows) do
		if type(window.macrobounds) == "table" then
			for i,rect in pairs(window.macrobounds) do
				if
					x >= rect[1] and x <= rect[3] and
					y >= rect[2] and y <= rect[4]
				then
					return {k,rect[5]}
				end
			end
		end
		for i,rect in pairs(window:bounds()) do
			if
				x >= rect[1] and x <= rect[3] and
				y >= rect[2] and y <= rect[4]
			then
				return {k,""}
			end
		end
	end
	return {0,""}
	
	
end

function hack.PlayerBindPress(pl,bind)
	if type(hack.control) == "number" then
		local comp = ents.GetByIndex(hack.control)
		if comp.control then
			if string.find(bind,"+attack") or string.find(bind,"+attack2") then
				return
			end
		end
	end
end

hook.Add("PlayerBindPress","hack.PlayerBindPress",hack.PlayerBindPress)

function hack.HUDPaint()
	if hack.GUI then
		if hack.GUI.char then
			local char = hack.GUI.char
			local char1 = char[#char]
			local cap
			local modsrc = {
				[79]="shift",
				[80]="rshift",
				[81]="alt",
				[82]="ralt",
				[83]="ctrl",
				[84]="rctrl",
			}
			local modout = {}
			for k,v in pairs(char) do
				if v == 79 or v == 80 then
					cap = true
				end
				if v >= 79 and v <= 84 then
					modout[modsrc[v]] = true
				end
			end
			
			local mod
			
			/*
			if char1 >= 80 and char1 <= 84 and char1 % 2 == 1 then
				mod = ({
					[80]="rightshift", //All the right-hand modifiers are broken
					[81]="alt",
					[82]="ralt",
					[83]="ctrl",
					[84]="rctrl",
				})[char1]
				char1 = char2
			end
			*/
			
			if not cap and (char1 >= 11 and char1 <= 36) then
				char1 = string.format("%c",char1+86)
			elseif cap then
				if char1 >= 11 and char1 <= 36 then
					char1 = string.format("%c",char1+54)
				else
					char1 = ({
						[0]="KP5",
						[1]=")",
						[2]="!",
						[3]="@",
						[4]="#",
						[5]="$",
						[6]="%",
						[7]="^",
						[8]="&",
						[9]="*",
						[10]="(",
						[47]="/",
						[48]="*",
						[49]="-",
						[50]="+",
						[52]=".",
						[53]="{",
						[54]="}",
						[55]=":",
						[56]='"',
						[58]="<",
						[59]=">",
						[60]="?",
						[61]="|",
						[62]="_",
						[63]="+",
						[64]="\n",
						[65]=" ",
						[66]="backspace",
						[67]="\t",
						[72]="insert",
						[73]="delete",
						[74]="home",
						[75]="end",
						[76]="pageup",
						[77]="pagedown",
						[80]="rshift",
						[81]="alt",
						[82]="ralt",
						[83]="ctrl",
						[84]="rctrl",
						[87]="menu",
						[88]="dU",
						[89]="dL",
						[90]="dD",
						[91]="dR",
						
					})[char1]
					/*
					if not char1 then
						char1 = nil
					end
					*/
				end
			elseif char1 >= 1 and char1 <= 10 then
				char1 = char1 - 1
			elseif char1 >= 37 and char1 <= 46 then
				char1 = char1 - 37
			elseif char1 >= 92 and char1 <= 103 then
				char1 = "F"..(char1 - 91)
			else
				char1 = ({
					[0]="KP5",
					[47]="/",
					[48]="*",
					[49]="-",
					[50]="+",
					[52]=".",
					[53]="[",
					[54]="]",
					[55]=";",
					[56]="'",
					[58]=",",
					[59]=".",
					[60]="/",
					[61]=[[\]],
					[62]="-",
					[63]="=",
					[64]="\n",
					[65]=" ",
					[66]="backspace",
					[67]="\t",
					[72]="insert",
					[73]="delete",
					[74]="home",
					[75]="end",
					[76]="pageup",
					[77]="pagedown",
					[80]="rshift",
					[81]="alt",
					[82]="ralt",
					[83]="ctrl",
					[84]="rctrl",
					[87]="menu",
					[88]="dU",
					[89]="dL",
					[90]="dD",
					[91]="dR",
				})[char1]
				/*
				if not char1 then
					char1 = nil
				end
				*/
			end
			
			if char1 then
				if char1 == 79 then
					char1 = "shift"
				elseif char1 == 80 then
					char1 = "rshift"
				end
				
				//if char1 ~= "shift" then
					Msg(char1)
				//end
			end
			
			hack.GUI.char = nil
			
			local comp = ents.GetByIndex(hack.control)
			
			//surface.PlaySound("hack/key"..math.random(1,3)..".wav")
			LocalPlayer():EmitSound("hack/key"..math.random(1,3)..".wav",500,math.random(95,110))
			comp.key = {
				key=char1,
				mod=modout,
				focus=comp.key.focus,
				last=CurTime(),
			}
		end
	end
end

hook.Add("HUDPaint","hack.HUDPaint",hack.HUDPaint)

function hack.Use()
	gui.EnableScreenClicker(true)
	surface.PlaySound("hack/logon.wav")
	
	if hack.GUI and hack.GUI.frame and hack.GUI.frame:IsVisible() then
		hack.GUI.frame:SetVisible(false)
		hack.GUI.frame:Remove()
	end
	
	hack.GUI = {}
	
	local frame = vgui.Create("Frame")
	frame:SetName("KeyboardSpy")
	
	function frame:Init()
	end
	
	function frame:OnKeyCodePressed(char)
		if not hack.GUI.char then
			hack.GUI.char = {}
		end
		table.insert(hack.GUI.char,1,char)
		/*
		local inc = 0
		
		if char == 79 then
			surface.PlaySound("hack/click2.wav")
		end
		
		if char >= 11 and char <= 36 then
			inc = 86
			if hack.GUI.shift then
				inc = 54
				hack.GUI.shift = false
				hack.GUI.shifttick = nil
			end
		elseif char == 79 then
			hack.GUI.shift = true
			hack.GUI.shifttick = 0
		end
		
		hack.GUI.lastkey = char
		
		if inc > 0 then
			char = string.format("%c",char+inc)
		end
		if char == 79 then
			char = ""
		else
			Msg(char,"\n")
		end
		*/
	end
	
	frame:SetVisible(true)
	frame:SetPos(-128,-128)
	
	hack.GUI.frame = frame
end

usermessage.Hook("hackE",hack.Use)

function hack.GUIMousePressed(mc)
	if hack.GUI and type(hack.control) == "number" then
		local comp = ents.GetByIndex(hack.control)
		
		local trace = {}
			trace.start = LocalPlayer():GetShootPos()
			trace.endpos = LocalPlayer():GetCursorAimVector()*64+trace.start
			trace.filter = LocalPlayer()
		local trace = util.TraceLine(trace)
		
		if trace.Entity ~= comp.Entity then
			gui.EnableScreenClicker(false)
			surface.PlaySound("hack/logoff.wav")
			
			local frame = hack.GUI.frame
			
			frame:SetVisible(false)
			frame:Remove()
			
			hack.GUI = nil
		end
		
		surface.PlaySound("hack/click1.wav")
		if mc > 100 then
			mc = mc - 107
		end
		comp.mc[mc].click = 1
	end
end
function hack.GUIMouseReleased(mc)
	if hack.GUI and type(hack.control) == "number" then
		local comp = ents.GetByIndex(hack.control)
		
		surface.PlaySound("hack/click2.wav")
		if mc > 100 then
			mc = mc - 107
		end
		comp.mc[mc].click = -1
	end
end

hook.Add("GUIMousePressed","hack.GUIMousePressed",hack.GUIMousePressed)
hook.Add("GUIMouseReleased","hack.GUIMouseReleased",hack.GUIMouseReleased)

/*
function hack.KeyPress(pl,key)
	if key == IN_ATTACK or key == IN_ATTACK2 or key == IN_USE or key == IN_RELOAD then
		if key == IN_ATTACK then
			key = 0
		elseif key == IN_ATTACK2 then
			key = 1
		elseif key == IN_USE then
			key = 0
		elseif key == IN_RELOAD then
			key = 1
		end
		if type(hack.control) == "number" then
			local comp = ents.GetByIndex(hack.control)
			if comp.control then
				surface.PlaySound("hack/click1.wav")
				comp.mc[key].click = 1
			end
		end
	end
end

hook.Add("KeyPress","hack.KeyPress",hack.KeyPress)

function hack.KeyRelease(pl,key)
	if key == IN_ATTACK or key == IN_ATTACK2 or key == IN_USE or key == IN_RELOAD then
		if key == IN_ATTACK then
			key = 0
		elseif key == IN_ATTACK2 then
			key = 1
		elseif key == IN_USE then
			key = 0
		elseif key == IN_RELOAD then
			key = 1
		end
		if type(hack.control) == "number" then
			local comp = ents.GetByIndex(hack.control)
			if comp.control then
				surface.PlaySound("hack/click2.wav")
				comp.mc[key].click = -1
			end
		end
	end
end

hook.Add("KeyRelease","hack.KeyRelease",hack.KeyRelease)
*/


usermessage.Hook("hackC",function(um)
	local self = ents.GetByIndex(um:ReadShort())
	if (!self) or (!self:IsValid()) then
		return
	end
	
	local ent = ents.GetByIndex(um:ReadShort())
	if (!ent) or (!ent:IsValid()) or (type(ent:GetTable().Drivers) ~= "table") or (ent:GetTable().Drivers.compatibility ~= "i64") then
		return
	end
	
	//Begin Compat
	local dims
	do
		local s = 30
		dims = {
			x = -10.5*s,
			y = -24.7*s,
			w = 21*s,
			h = 16.1*s,
			s = s
		}
	end
	
	local ScrW = function()
		return dims.w
	end
	
	local ScrH = function()
		return dims.h
	end
	
	local GM = self
	//End Compat
	
	table.insert(GM.windows,1,hack.InitWindow(self,
	{
		caption = "New Hardware Wizard",
		options = {
				close = true,
				minimize = true,
			},
		x = ScrW()*.5 - 128,
		y = ScrH()*.5 - 64,
		w = 256,
		h = 128,
		_ = {Driver = ent:GetTable().Drivers},
		draw = function(self)
			if not self.visible then //The draw function will still be called even if your window is minimized, so check to see if it is minimized first.
				return
			end
			local s = hack.scheme
			self:DrawWindowPre()
			
			local driver = self._.Driver
			
			self:DrawText("New hardware detected!\n["..driver.name.."]\nType: "..driver.type.."\n"..driver.generic.." device.\nManufacturer: "..driver.corporation,"Trebuchet18",4,4,s.f1)
			self:DrawText("(C) Night-Eagle 2007","Trebuchet18",self.w-4,self.h-20,s.f1,2)
			
			//hack.focus[1] = -1 //If this was uncommented, the button below could never be clicked or highlighted, keep this in mind.
			//IMPORTANT: You should ONLY set this to -1 if hack.focus[1] == self.focus.
			//hack.focus[1] holds the key of the window that should receive mouse clicks.
			//(Note - When a window is clicked, its key is set to 1 - this due to the draw order algorithm.)
			
			//When using the "button" type form, it returns -1 for release-clicked, nil for not clicked, 1 for start-clicked, and 2 for hold-clicked.
			//You typically only want to execute code when self:DrawForm returns a -1 (Negative 1).
			//If you execute code when it is positive 1, then you are not letting the user release the button.
			if self:DrawForm("button1","button",{
				x = 8,
				y = self.h-26,
				w = 32,
				h = 18,
				label = "OK",
				}) == -1
			then
				self:close()
			end
			self:DrawWindowPost()
		end,
	}
	))
end)

//Includes (To be expanded later)

//hsv.lua

/*
hack.hsvf = {
	function(v,p,q,t,alpha)
		surface.SetDrawColor(v,t,p,alpha)
	end,
	function(v,p,q,t,alpha)
		surface.SetDrawColor(q,v,p,alpha)
	end,
	function(v,p,q,t,alpha)
		surface.SetDrawColor(p,v,t,alpha)
	end,
	function(v,p,q,t,alpha)
		surface.SetDrawColor(p,q,v,alpha)
	end,
	function(v,p,q,t,alpha)
		surface.SetDrawColor(t,p,v,alpha)
	end,
	function(v,p,q,t,alpha)
		surface.SetDrawColor(v,p,q,alpha)
	end,
}

function hack.hsv(h,s,v,alpha)
	if h == 360 then
		h = 0
	end
	local r, g, b
	if s ~= 0 then
		local i = math.floor(h/60)
		local f = h/60 - i
		local p = v*(1-s)
		local q = v*(1-f*s)
		local t = v*(1-(1-f)*s)
		
		hack.hsvf[i+1](v,p,q,t,alpha)
	else
		surface.SetDrawColor(v,v,v,alpha)
	end
end
*/




































